﻿using System;
using System.Linq;
using System.Text;
using StockFinder.Model;
using System.Diagnostics;
using StockFinder.StockLists;
using StockFinder.StockLists.Indexes;
using StockFinder.YahooFinance;
using StockFinder.Indicators.Day.ClosePrice;
using StockFinder.Model.Constants;
using System.Net.Mail;
using System.Net;
using System.IO;

namespace StockFinder.Consoles.DadRSI
{
    class Program
    {
        /* PRICE <= 30 RSI(20) AND 10% < 2 YEAR HIGH */
        /* S&P 500 | NASDAQ 100 | FTSE 250 */

        const int RSI_FILTER = 30;
        const int YEARS_BACK_TO_DOWNLOAD = 2;
        const int PERCENT_OFF_HIGH = 10;

        static readonly IStockList[] _StockLists = new IStockList[] 
            { 
                new FinvizOnlineDowJonesStockList(),
                new FinvizOnlineSnP500StockList(),
                new YahooFinanceOnlineFtse250StockList()
            };

        static readonly YahooFinanceOnlineStockPriceHistoryExtractor _YahooPricesExtractor = new YahooFinanceOnlineStockPriceHistoryExtractor();
        static readonly ExponentialMovingAverageWilderRelativeStrengthIndexClosePriceDayIndicator _Rsi20 = new ExponentialMovingAverageWilderRelativeStrengthIndexClosePriceDayIndicator(20, DayIndicatorNames.CLOSE_RSI20);
        static readonly ExponentialMovingAverageWilderRelativeStrengthIndexClosePriceDayIndicator _Rsi14 = new ExponentialMovingAverageWilderRelativeStrengthIndexClosePriceDayIndicator(14, DayIndicatorNames.CLOSE_RSI14);

        static void Main(string[] args)
        {                      
            //RunTest();
            
            RunAll();
        }

        private static void RunTest()
        {
            CheckFilter("LWDB.L");
        }

        private static void RunAll()
        {              
            var output = new StringBuilder();
            DadRsiResult result;

            output.AppendLine("Symbol,RSI(20),RSI(14),%offHigh,Index");

            foreach (var stockList in _StockLists)
            {
                Console.WriteLine("Getting symbols for " + stockList.Name);

                Console.WriteLine(string.Format("Downloaded {0} symbols", stockList.Count));

                foreach (var symbol in stockList)
                {
                    result = CheckFilter(symbol.Name);

                    if (result.Succeeded)
                    {
                        output.AppendLine(string.Format("{0},{1},{2},{3},{4}",
                            symbol,
                            result.Rsi20, //rsi 20
                            result.Rsi14, //rsi 14
                            Math.Round(result.PercentOffHigh, 2), //% off high
                            stockList.Name));
                    }
                }
            }

            Console.Write("Complete");

            Console.WriteLine("Emailing results");
            try
            {
                SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
                client.EnableSsl = true;
                MailAddress from = new MailAddress("ssattin@gmail.com", "Simon Sattin");
                MailMessage message = new MailMessage(from, from);
                message.Subject = "RSI <= 30 Daily List";
                NetworkCredential myCreds = new NetworkCredential("ssattin@gmail.com", "bergkamp_10", "");
                client.Credentials = myCreds;

                message.Body = output.ToString();

                UnicodeEncoding uniEncoding = new UnicodeEncoding();
                using (MemoryStream ms = new MemoryStream())
                {
                    using (StreamWriter sw = new StreamWriter(ms, uniEncoding))
                    {
                        sw.Write(output.ToString());

                        //message.Attachments.Add(new Attachment(ms, "Stocks.csv"));

                        client.Send(message);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }           
        }

        private static DadRsiResult CheckFilter(string symbol)
        {
            var result = new DadRsiResult();

            Console.WriteLine("Getting prices for " + symbol);

            var prices = _YahooPricesExtractor.GetHistoricPrices(new Symbol() { Name = symbol }, DateTime.Today.AddYears(-YEARS_BACK_TO_DOWNLOAD), DateTime.Today);

            if (prices == null)
            {
                Debug.WriteLine("No prices found");
            }
            else
            {
                Console.WriteLine(string.Format("Downloaded {0} prices.", prices.Count));

                Console.WriteLine("Applying RSI 20");

                _Rsi20.ApplyIndicator(prices);
                _Rsi14.ApplyIndicator(prices);

                Console.WriteLine("Applying filter");

                var price = prices.First();

                var highestClose = prices.Max(p => p.AdjustedClose);

                var percentOffHigh = ((highestClose - price.AdjustedClose) / highestClose) * 100;

                if (percentOffHigh >= PERCENT_OFF_HIGH &&
                    price.DayIndicators[_Rsi20.IndicatorName] < RSI_FILTER)
                {
                    result.Succeeded = true;
                    result.Rsi14 = Math.Round(price.DayIndicators[_Rsi14.IndicatorName], 2);
                    result.Rsi20 = Math.Round(price.DayIndicators[_Rsi20.IndicatorName], 2);
                    result.PercentOffHigh = Math.Round(percentOffHigh, 2);
                    result.Symbol = symbol;  
                }
            }

            return result;
        }
    }
}
